package com.ciei.dpagm.util;

import org.apache.commons.lang3.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Stack;

/**
 * 指令分割工具类
 * @author fangnuozhou
 * @date 2022/09/23
 */
public class CommandSplitUtils {

    /**
     * 转义字符
     */
    private static final Character TRANSFER_MEANING_CHARACTER = '\\';

    /**
     * 分割原始指令，并处理转义字符
     * @param originalCommand   原始指令
     * @param splitCharacter    分割的字符
     * @return
     */
    public static String[] splitCommand(String originalCommand, String splitCharacter) {
        return splitCommand(originalCommand, splitCharacter, false);
    }

    /**
     * 分割原始指令，并处理转义字符
     * @param originalCommand   原始指令
     * @param splitCharacter    分割的字符
     * @param transferMeaning   是否转义字符
     * @return					分割的结果
     */
    public static String[] splitCommand(String originalCommand, String splitCharacter, boolean transferMeaning) {
        if (StringUtils.isEmpty(originalCommand) || StringUtils.isEmpty(splitCharacter)) {
            return new String[] { originalCommand };
        }
        char[] originalCharArray = originalCommand.toCharArray();
        char[] splitCharArray = splitCharacter.toCharArray();
        // 分割好的指令
        List<String> splitStringList = new ArrayList<>();
        // 存储不与分割符匹配的字符
        Stack<Character> storeCharacters = new Stack<>();
        // 存储与分割符匹配的字符
        Stack<Character> storeSplitMatchCharacters = new Stack<>();
        // 当前与分割符匹配的字符的位置
        int splitCharacterMatchIndex = 0;
        // 是否转义下一个字符
        boolean transferNextChar = false;
        for (char originalChar : originalCharArray) {
            if (transferNextChar) {
                storeCharacters.push(originalChar);
                transferNextChar = false;
                continue;
            }
            if (transferMeaning && TRANSFER_MEANING_CHARACTER.equals(originalChar)) {
                transferNextChar = true;
                continue;
            }
            if (Objects.equals(originalChar, splitCharArray[splitCharacterMatchIndex])) {
                splitCharacterMatchIndex++;
                if (splitCharacterMatchIndex == splitCharArray.length) {
                    StringBuilder stringBuilder = new StringBuilder();
                    storeCharacters.forEach(stringBuilder::append);
                    splitStringList.add(stringBuilder.toString());

                    storeCharacters.clear();
                    storeSplitMatchCharacters.clear();
                    splitCharacterMatchIndex = 0;
                } else {
                    storeSplitMatchCharacters.push(originalChar);
                }
            } else {
                if (!storeSplitMatchCharacters.isEmpty()) {
                    storeCharacters.addAll(storeSplitMatchCharacters);
                    storeSplitMatchCharacters.clear();
                }
                storeCharacters.add(originalChar);
                splitCharacterMatchIndex = 0;
            }
        }
        if (!storeCharacters.isEmpty()) {
            StringBuilder stringBuilder = new StringBuilder();
            storeCharacters.forEach(stringBuilder::append);
            splitStringList.add(stringBuilder.toString());
        }

        String[] splitStrings = new String[splitStringList.size()];
        for(int i = 0; i < splitStringList.size(); i++) {
            splitStrings[i] = splitStringList.get(i);
        }
        return splitStrings;
    }

}
